#include <stdio.h>
#include <thread>
#include <string.h>
#include "taiic_uart_sum.h"
#include <fstream>
#include "rk_debug.h"
#include <unistd.h> // Unix 标准函数定义
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h> // 文件控制定义
#include <iostream>
#include <termios.h> // PPSIX 终端控制定义
#include <cstring>   // 字符串功能
#include <errno.h>   // 错误号定义
#include <mutex>
#include <assert.h>
#include <cstdint>
#include <cstddef>
#include <sstream>
#include <iomanip> // 必须包含此头文件,setw()
#include <cstdio>
#include <sys/stat.h>
#include <vector>
#include <algorithm> // for std::copy
#include <ctime>
#include <dirent.h>
#include <queue>
#include <../model/taiic_opencv.h>

using namespace std;
using namespace cv;
int version = 0; // version:1表示只发送结果，不发送传感器数据

bool ptt_up_flag = false; // 定义并初始化变量
int custom_tl = 0;

bool only_air = false;
bool only_bone = false;
bool only_air_bone = false;
bool only_video_air = false;
bool only_video_bone = false;
bool only_video_air_bone = false;

bool AudioModelInf_or_DataType = true; // 默认为true，即模型推理模块
bool only_mic_custom_tl = false;       // 自定义音频时长，默认false

std::mutex mtx_soc_sendData;

#define SOC_MIC_LENGTH (SEND_FRAME_HEAD_LEN + PER_AUDIO_FRAME_LEN)
uint8_t soc_buffer_mic_air[SOC_MIC_LENGTH] = {0};
uint8_t soc_buffer_mic_bone[SOC_MIC_LENGTH] = {0};
uint8_t soc_buffer_mic_air_bone[SOC_MIC_LENGTH + PER_AUDIO_FRAME_LEN] = {0};
// 数据队列
std::queue<std::vector<uint8_t>> dataQueue;

static mutex mtx_ringbuffer;
std::ofstream file_pcm;

struct termios options;
// #define BAUD_RATE_485 B230400 // #define BAUD_RATE_485 9600
#define BAUD_RATE_485 B115200 // 适配三代机的波特率
struct stat fileStat;         // get pcm file size(byte)

bool sub_flg = false; // 判断UART的发送方向(副板/上位机)，默认false发往副板，true发往上位机

tSppFrameDataCallback *s_sppFrameDataCallback = NULL; // 蓝牙回调
void taiic_spp_frame_data_callback(tSppFrameDataCallback spp_frame_data)
{
    s_sppFrameDataCallback = spp_frame_data;
}

// ai func callback
tAiFrameDataCallback *s_aiFrameDataCallback = NULL; // 定义ai回调方法变量
void taiic_ai_frame_data_callback(tAiFrameDataCallback ai_frame_data)
{
    s_aiFrameDataCallback = ai_frame_data;
}

// 测试模块数据回调
tTestFrameDataCallback *s_testFrameDataCallback = NULL; // 定义测试模块回调方法变量
void taiic_test_frame_data_callback(tTestFrameDataCallback test_frame_data)
{
    s_testFrameDataCallback = test_frame_data;
}
/*--------------------------------crc-----------------------------------*/
unsigned short calc_crc16(const uint8_t *buffer, unsigned int size, unsigned short crc)
{
    if (NULL != buffer && size > 0)
    {
        while (size--)
        {
            crc = (crc >> 8) | (crc << 8);
            crc ^= *buffer++;
            crc ^= ((uint8_t)crc) >> 4;
            crc ^= crc << 12;
            crc ^= (crc & 0xFF) << 5;
        }
    }
    return crc;
}

unsigned short big_to_little_u16(void *data)
{
    uint8_t in_data[2] = {0};
    uint8_t tmp_data[2] = {0};
    unsigned short out_data = 0;

    memcpy(in_data, data, sizeof(unsigned short));
    tmp_data[0] = in_data[1];
    tmp_data[1] = in_data[0];
    memcpy(&out_data, tmp_data, sizeof(tmp_data));

    return out_data;
}

// 将一个uint8_t转换为两个字符的16进制字符串
std::string toHex(uint8_t byte)
{
    std::stringstream ss;
    ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
    return ss.str();
}

/*--------------------485-----------------------------------*/
void UART0_INIT(int fd)
{
    if (tcgetattr(fd, &options) != 0)
    {
        printf("tcgetattr fail\n");
    }

    cfsetospeed(&options, BAUD_RATE_485); // output
    // 修改控制模式，保证程序不会占用串口
    options.c_cflag |= CLOCAL;
    // 修改控制模式，使得能够从串口中读取输入数据
    options.c_cflag |= CREAD;

    options.c_cflag &= ~CRTSCTS; // 0 控制流

    options.c_cflag &= ~CSIZE; //

    options.c_cflag |= CS8;     // 8 设置数据位
    options.c_cflag &= ~CSTOPB; // 1 停止位
                                // 无奇偶校验
    options.c_cflag &= ~PARENB;
    options.c_iflag &= ~INPCK;
    // 原始数据输出模式
    options.c_oflag &= ~OPOST;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    // 设置等待时间和最小接收字符
    options.c_cc[VTIME] = 1; // 读取一个字符等待1*(1/10)s
    options.c_cc[VMIN] = 1;  // 读取字符的最少个数为1
    // 如果发生数据溢出，接收数据，但是不再读取 刷新收到的数据但是不读
    tcflush(fd, TCIFLUSH);
    // 激活配置（将修改后的termios数据设置到串口中）
    if (tcsetattr(fd, TCSANOW, &options) != 0)
    {
        printf("tcsetattr fail\n");
    }
}

/*---------------------youxian 485 send function--------------------*/
void bat_send_func_485(int charge_state, int vol, int cap) // 有线485上传电量信息:电池电压和电池容量
{
    uint8_t send_data[4] = {0};

    send_data[0] = charge_state;

    int_to_hex_array(vol, &send_data[1]);
    send_data[3] = cap;

    youxian_485_upload(battery_status_notify_cmd, &send_data, sizeof(send_data));
}

void mode_state_send_func_485(int stateValue) // 有线485上传模式状态
{
    uint8_t send_data[2] = {0};
    send_data[1] = stateValue; // 模式状态值

    youxian_485_upload(mode_state_send_cmd, &send_data, sizeof(send_data));
}

void lip_label_send_func_485(int label) // 有线485上传唇图标签
{
    uint8_t send_data[4] = {0};
    intToUint8Array(label, send_data);

    youxian_485_upload(lip_label_send_cmd, &send_data, sizeof(send_data));
}

// 有线485上传图像数据: 数据包长度1028,其中1024表示图像数据长度
void image_data_send_func_485(int pkg_num, int pkg_size, uint8_t *data)
{
    uint8_t send_data[SEND_PKG_SIZE] = {0}; // 1028

    send_data[1] = pkg_num; // int_to_hex_array(pkg_num,&send_data[1]);
    int_to_hex_array(pkg_size, &send_data[2]);
    memcpy(&send_data[4], data, pkg_size);

    youxian_485_upload(img_data_send_cmd, &send_data, sizeof(send_data));
}

// youxian 485 send ptt key value
void ptt_key_value_send_func_485(int keyValue) // ptt key value
{
    uint8_t send_data = keyValue;

    youxian_485_upload(up_data_switch_cmd, &send_data, sizeof(send_data));
}

void youxian_485_upload(protocal_list_t instruct, void *data, unsigned short length)
{
    uint8_t send_buffer[FRAME_BUFFER_LENGTH_MAX] = {0};
    unsigned short data_length = 0;
    unsigned short check_sum = 0;

    // 填充帧内容
    send_buffer[FRAME_FLAG_INDEX] = 0xFE;                    // 帧头标准
    send_buffer[FRAME_FROM_INDEX] = 0x04;                    // 从主板
    send_buffer[FRAME_TO_INDEX] = 0x08;                      // 发往上位机
    send_buffer[FRAME_COMMAND_ID_INDEX] = (uint8_t)instruct; // 指令

    data_length = big_to_little_u16(&length);
    memcpy(&send_buffer[FRAME_DATA_LENGTH_INDEX], &data_length, sizeof(data_length)); // 有效数据长度
    memcpy(&send_buffer[FRAME_DATA_START_ADDR_INDEX], data, length);                  // 有效数据
    // 计算校验值
    check_sum = calc_crc16(send_buffer, FRAME_CHECK_DATA_LENGTH(length), CHECKSUM_INIT_VALUE);
    // printf("check_sum = %x\n", check_sum);
    check_sum = big_to_little_u16(&check_sum);
    // printf("check_sum = %x\n", check_sum);
    memcpy(&send_buffer[FRAME_CHECKSUM_INDEX(length)], &check_sum, sizeof(check_sum));

    // print send data
    /*printf("Total length:%d,485 send data: ", FRAME_TOTAL_LENGTH(length));
    for (int i = 0; i < FRAME_TOTAL_LENGTH(length); i++)
    {
        printf("%02x ", ((uint8_t *)send_buffer)[i]);
    }
    printf("\n");*/

    rs_send_uint8(send_buffer, FRAME_TOTAL_LENGTH(length));      // youxian 485 send
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 0.1s
}

// 485 youxian send
void rs_send(const char *send_buf, int data_len) // 9600 ( 0 8 1 N)
{
    int fd = open(UART_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY);
    UART0_INIT(fd);
    // send
    int len = write(fd, send_buf, data_len);
    if (len == data_len)
    {
        close(fd);
    }
    else
    {
        tcflush(fd, TCOFLUSH);
    }
}

// 485 youxian send uint8
void rs_send_uint8(uint8_t *send_buf, int data_len) // 9600 ( 0 8 1 N)
{
    int fd = open(UART_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY);
    UART0_INIT(fd);
    // send
    int len = write(fd, send_buf, data_len);
    if (len == data_len)
    {
        close(fd);
    }
    else
    {
        tcflush(fd, TCOFLUSH);
    }
}

/*---------------------Ring Buffer-------------------------*/
void RingBuf_Taiic_U::initRingbuffer(void)
{
    if (pHead == NULL)
    {
        pHead = (uint8_t *)malloc(bufferSize);
    }
    pValid = pValidTail = pHead;
    pTail = pHead + bufferSize;
    validLen = 0;
}
/*
 * function:向缓冲区中写入数据
 * param:@buffer 写入的数据指针
 * 		 @addLen 写入的数据长度
 * return:-1:写入长度过大
 * 		  -2:缓冲区没有初始化
 * */
int RingBuf_Taiic_U::writeRingbuffer(uint8_t *buffer, int addLen)
{
    if (addLen > bufferSize)
        return -2;
    if (pHead == NULL)
        return -1;
    assert(buffer);

    // 将要存入的数据copy到pValidTail处
    if (pValidTail + addLen > pTail) // 需要分成两段copy
    {
        int len1 = pTail - pValidTail;
        int len2 = addLen - len1;
        memcpy(pValidTail, buffer, len1);
        memcpy(pHead, buffer + len1, len2);
        pValidTail = pHead + len2; // 新的有效数据区结尾指针
    }
    else
    {
        memcpy(pValidTail, buffer, addLen);
        pValidTail += addLen; // 新的有效数据区结尾指针
    }

    // 需重新计算已使用区的起始位置
    if (validLen + addLen > bufferSize)
    {
        int moveLen = validLen + addLen - bufferSize; // 有效指针将要移动的长度
        if (pValid + moveLen > pTail)                 // 需要分成两段计算
        {
            int len1 = pTail - pValid;
            int len2 = moveLen - len1;
            pValid = pHead + len2;
        }
        else
        {
            pValid = pValid + moveLen;
        }
        validLen = bufferSize;
    }
    else
    {
        validLen += addLen;
    }

    return 0;
}
/*
 * function:从缓冲区内取出数据
 * param   :@buffer:接受读取数据的buffer
 *		    @len:将要读取的数据的长度
 * return  :-1:没有初始化
 *	 	    >0:实际读取的长度
 * */
unsigned int RingBuf_Taiic_U::readRingbuffer(uint8_t *buffer, unsigned int len)
{
    if (pHead == NULL)
        return -1;

    assert(buffer);

    if (validLen == 0)
        return 0;

    if (len > validLen)
        len = validLen;

    if (pValid + len > pTail) // 需要分成两段copy
    {
        int len1 = pTail - pValid;
        int len2 = len - len1;
        memcpy(buffer, pValid, len1);       // 第一段
        memcpy(buffer + len1, pHead, len2); // 第二段，绕到整个存储区的开头
        pValid = pHead + len2;              // 更新已使用缓冲区的起始
    }
    else
    {
        memcpy(buffer, pValid, len);
        pValid = pValid + len; // 更新已使用缓冲区的起始
    }
    validLen -= len; // 更新已使用缓冲区的长度
    return len;
}

/*
 * function:获取已使用缓冲区的长度
 * return  :已使用的buffer长度
 * */
unsigned int RingBuf_Taiic_U::getRingbufferValidLen(void)
{
    return validLen;
}
/*
 * function:释放环形缓冲区
 * */
void RingBuf_Taiic_U::releaseRingbuffer(void)
{
    if (pHead != NULL)
        free(pHead);
    pHead = NULL;
}
/*-----------------------------------audio analysis---------------------*/
void appendToPcmFile(const char *filename, uint8_t *data, unsigned int length)
{
    file_pcm.open(filename, std::ios::binary | std::ios::app); // 追加模式

    if (!file_pcm.is_open())
    {
        // 处理文件打开失败的情况
        std::cerr << "Failed to open file for appending: " << filename << std::endl;
        return;
    }
    // 将数据写入文件
    file_pcm.write(reinterpret_cast<const char *>(data), length);
    // 检查是否所有数据都已写入
    if (!file_pcm)
    {
        std::cerr << "Failed to write data to file: " << filename << std::endl;
    }
    // 关闭文件
    file_pcm.close();
}
// 判断文件是否存在
bool fileExists(const char *filename)
{
    FILE *file = fopen(filename, "r");
    if (file != nullptr)
    {
        fclose(file);
        return true;
    }
    return false;
}
// Get file size
long getFileSize(const char *filename)
{
    long size = 0;
    if (stat(filename, &fileStat) == 0)
    {
        size = fileStat.st_size;
        // std::cout << "PCM文件大小(字节):" << fileStat.st_size << std::endl;
    }
    else
    {
        // std::cerr << "无法获取文件信息: " << filename << std::endl;
        size = -1;
    }
    return size;
}
//
void int_to_hex_array(int value, uint8_t *array)
{
    array[0] = static_cast<uint8_t>(value >> 8); // 高位有效字节
    array[1] = static_cast<uint8_t>(value);      // 低位有效字节
}
////////////////////////////uart_commid///////////////////////////

// 打开串口设备
int open_serial_port(void)
{
    char error_info[256] = {0};

    serial_fd = open(SERIAL_PORT, O_RDWR);
    if (serial_fd == -1)
    {
        sprintf(error_info, "open_port: Unable to open %s\n", SERIAL_PORT);
        perror(error_info);
        return -1;
    }
    return 0;
}

// 设置串口参数
int set_serial_attribs(void)
{
    struct termios tty;
    memset(&tty, 0, sizeof(tty));
    if (tcgetattr(serial_fd, &tty) != 0)
    {
        perror("tcgetattr");
        return -1;
    }
    // 设置波特率
    cfsetispeed(&tty, BAUD_RATE);
    cfsetospeed(&tty, BAUD_RATE);
    printf("baud_rate = %d\n", BAUD_RATE);
#if 0
    // 设置CSIZE为CS8，即8位数据长度
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;
    // 设置PARENB为0，即无校验位
    tty.c_cflag &= ~PARENB;
    // 设置CSTOPB为0，即1位停止位
    tty.c_cflag &= ~CSTOPB;
    // 设置CRTSCTS为0，即不使用硬件流控制
    tty.c_cflag &= ~CRTSCTS;
#else
    tty.c_cflag |= termios_c_cflag;
#endif
    // 设置CLOCAL和CREAD，使能接收器和本地模式
    tty.c_cflag |= (CLOCAL | CREAD);
    // 设置ICANON为0，即非规范模式，这样read就不会受行缓冲的影响
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    // 设置OPOST为0，即禁用输出处理
    tty.c_oflag &= ~OPOST;
    tty.c_oflag &= ~(ONLCR | OCRNL);
    // 设置ICANON为0，即非规范模式
    tty.c_iflag &= ~(BRKINT | INPCK | ISTRIP);
    tty.c_iflag &= ~(ICRNL | INLCR);
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);
    // 设置VMIN为1，VMAX为0，这样read就会一直阻塞，直到有数据可读
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 0;
    if (tcsetattr(serial_fd, TCSANOW, &tty) != 0)
    {
        perror("tcsetattr");
        return -1;
    }
    return 0;
}

// 串口接收数据线程函数
void *serial_recv_pthread_function(void *arg)
{
    int ret = 0;
    uint8_t recv_buffer[512];
    int len = 0;

    while (true)
    {
        // 读取数据
        len = read(serial_fd, recv_buffer, sizeof(recv_buffer));
        if (len < 0)
        {
            perror("read");
            close(serial_fd);
            pthread_exit((void *)&ret);
        }
        else
        {
            // 向缓冲区中写入串口数据
            mtx_ringbuffer.lock();
            ret = serialData.writeRingbuffer(recv_buffer, len);
            mtx_ringbuffer.unlock();
        }
    }
}

// 串口发送数据函数
int serial_send_function(void *data, unsigned short data_len)
{
    int ret;

    if (data == NULL)
    {
        return -1;
    }

    ret = write(serial_fd, data, data_len);

    /*printf("send data: ");
    for (int i = 0; i < ret; i++)
    {
        printf("%02x ", ((uint8_t *)data)[i]);
    }
    printf("\n");*/

    return ret;
}

// 音频数据响应函数：0x20
void audio_response_func(uint8_t *data, unsigned int length)
{
    printf("response func: length=%d, data=%02x\n", length, data[0]);
}

// 副板固件版本号响应函数
void subplate_firmware_version_response_func(uint8_t *data, unsigned int length)
{
    /*printf("subplate_firmware_version_num:\n");
    for(int i=0;i<length;i++)
    {
        printf("%02x ",data[i]);
    }
    printf("\n");*/

    printf("subplate firware version:%d.%d.%d.%d\n", data[1], data[2], data[3], data[4]);
}

int audio_frame_analysis_function(uint8_t *data, unsigned int length)
{
    int ret = 0;
    if ((data == NULL) || (length < 4)) // 音频帧头有音频类型、帧号占有3个字节，数据长度 如果小于4，代表帧不合格直接返回
    {
        return -1;
    }
    else
    {
        // 获取音频帧帧头内容
        // audioAnalysis.pdata = reinterpret_cast<uint8_t *>(data);
        audioAnalysis.pdata = data;
        audioAnalysis.audio_type = audioAnalysis.pdata[0];

        memcpy(&audioAnalysis.frame_num, &audioAnalysis.pdata[1], 2); // memcpy(&audioAnalysis.frame_num, &audioAnalysis.pdata[1], sizeof(audioAnalysis.frame_num));
        audioAnalysis.frame_num = big_to_little_u16(&audioAnalysis.frame_num);
        // 20240603 add///////////////////
        audioAnalysis.dif = audioAnalysis.frame_num - audioAnalysis.last_frame_num;
        // printf("dif=%d,frame_cnt=%d,last_frame_cnt=%d\n", audioAnalysis.frame_num - audioAnalysis.last_frame_num, audioAnalysis.frame_num, audioAnalysis.last_frame_num);
        audioAnalysis.last_frame_num = audioAnalysis.frame_num;
        ////////////////////////////////
        audioAnalysis.audio_data = audioAnalysis.pdata + 3;
        audioAnalysis.audio_data_length = length - 3;

        if ((only_mic_custom_tl) && (audioAnalysis.audio_type == 1))
        {
            printf("custom air audio length:%d ms,num %d,len %d,type=%d\n", custom_tl, audioAnalysis.frame_num, audioAnalysis.audio_data_length, audioAnalysis.audio_type);
            if (audioAnalysis.frame_num == 1)
            {
                memset(soc_buffer_mic_air, 0, SOC_MIC_LENGTH);

                soc_buffer_mic_air[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
                soc_buffer_mic_air[1] = 6;
                soc_buffer_mic_air[3] = dataType_air; // 00 02表示气导数据
            }
            intToUint8Array(audioAnalysis.frame_num, &soc_buffer_mic_air[4]);
            intToUint8Array(audioAnalysis.audio_data_length, &soc_buffer_mic_air[8]);
            memcpy(&soc_buffer_mic_air[SEND_FRAME_HEAD_LEN], audioAnalysis.audio_data, audioAnalysis.audio_data_length * sizeof(uint8_t));

            mtx_soc_sendData.lock();
            serverSocket.sendData(soc_buffer_mic_air, SOC_MIC_LENGTH);
            mtx_soc_sendData.unlock();
        }
        else if ((!only_mic_custom_tl) && (!AudioModelInf_or_DataType))
        {
            if (audioAnalysis.audio_type == 2)
            {
                if (audioAnalysis.frame_num == 1)
                {
                    memset(soc_buffer_mic_bone, 0, SOC_MIC_LENGTH);
                    soc_buffer_mic_bone[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
                    soc_buffer_mic_bone[1] = 6;
                    soc_buffer_mic_bone[3] = dataType_bone; // 00 04表示骨导数据
                }
                intToUint8Array(audioAnalysis.frame_num, &soc_buffer_mic_bone[4]);

                intToUint8Array(audioAnalysis.audio_data_length, &soc_buffer_mic_bone[8]);
                memcpy(&soc_buffer_mic_bone[SEND_FRAME_HEAD_LEN], audioAnalysis.audio_data, audioAnalysis.audio_data_length * sizeof(uint8_t));

                if (!ptt_up_flag)
                {
                    if ((only_bone) || (only_video_bone))
                    {
                        printf("soc_bone:%d\n", audioAnalysis.frame_num);
                        mtx_soc_sendData.lock();
                        serverSocket.sendData(soc_buffer_mic_bone, SOC_MIC_LENGTH);
                        mtx_soc_sendData.unlock();
                    }
                }
            }
            else if (audioAnalysis.audio_type == 1)
            {
                if (audioAnalysis.frame_num == 1)
                {
                    memset(soc_buffer_mic_air, 0, SOC_MIC_LENGTH);

                    soc_buffer_mic_air[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
                    soc_buffer_mic_air[1] = 6;
                    soc_buffer_mic_air[3] = dataType_air; // 00 02表示气导数据
                }

                intToUint8Array(audioAnalysis.frame_num, &soc_buffer_mic_air[4]);
                intToUint8Array(audioAnalysis.audio_data_length, &soc_buffer_mic_air[8]);
                memcpy(&soc_buffer_mic_air[SEND_FRAME_HEAD_LEN], audioAnalysis.audio_data, audioAnalysis.audio_data_length * sizeof(uint8_t));

                if (!ptt_up_flag)
                {
                    if (only_air || only_video_air)
                    {
                        printf("soc_air:%d\n", audioAnalysis.frame_num);
                        mtx_soc_sendData.lock();
                        serverSocket.sendData(soc_buffer_mic_air, SOC_MIC_LENGTH);
                        mtx_soc_sendData.unlock();
                    }
                }
            }
            else if (audioAnalysis.audio_type == 3)
            {
                if (audioAnalysis.frame_num == 1)
                {
                    memset(soc_buffer_mic_air_bone, 0, SOC_MIC_LENGTH + PER_AUDIO_FRAME_LEN);

                    soc_buffer_mic_air_bone[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
                    soc_buffer_mic_air_bone[1] = 6;
                    soc_buffer_mic_air_bone[3] = dataType_air_bone; // 00 06表示air+bone
                }

                intToUint8Array(audioAnalysis.frame_num, &soc_buffer_mic_air_bone[4]);
                intToUint8Array(audioAnalysis.audio_data_length, &soc_buffer_mic_air_bone[8]);
                memcpy(&soc_buffer_mic_air_bone[SEND_FRAME_HEAD_LEN], audioAnalysis.audio_data, audioAnalysis.audio_data_length * sizeof(uint8_t));

                if (!ptt_up_flag)
                {
                    if (only_air_bone || only_video_air_bone)
                    {
                        printf("soc_air_bone:%d\n", audioAnalysis.frame_num);
                        mtx_soc_sendData.lock();
                        serverSocket.sendData(soc_buffer_mic_air_bone, SOC_MIC_LENGTH + PER_AUDIO_FRAME_LEN);
                        mtx_soc_sendData.unlock();
                    }
                }
            }
        }
        else if ((!only_mic_custom_tl) && (AudioModelInf_or_DataType)) // true:model inference
        {
            if ((audioAnalysis.audio_type == 1) && (audioAnalysis.frame_num < AI_COUNT)) // 气导原始数据
            {
                // printf("num %d,len %d,type=%d\n", audioAnalysis.frame_num, audioAnalysis.audio_data_length, audioAnalysis.audio_type);
                appendToPcmFile(audioAnalysis.air_filename, audioAnalysis.audio_data, audioAnalysis.audio_data_length);

                /*------------------model:air audio data send---------------------*/
                if (audioAnalysis.frame_num == 1)
                {
                    memset(soc_buffer_mic_air, 0, SOC_MIC_LENGTH);

                    soc_buffer_mic_air[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
                    soc_buffer_mic_air[1] = 6;
                    soc_buffer_mic_air[3] = dataType_air; // 00 02表示气导数据
                }

                intToUint8Array(audioAnalysis.frame_num, &soc_buffer_mic_air[4]);
                intToUint8Array(audioAnalysis.audio_data_length, &soc_buffer_mic_air[8]);
                memcpy(&soc_buffer_mic_air[SEND_FRAME_HEAD_LEN], audioAnalysis.audio_data, audioAnalysis.audio_data_length * sizeof(uint8_t));

                // printf("model:soc_air:%d\n", audioAnalysis.frame_num);
                if (version != 0)
                {
                    mtx_soc_sendData.lock();
                    serverSocket.sendData(soc_buffer_mic_air, SOC_MIC_LENGTH);
                    mtx_soc_sendData.unlock();
                }
                ////////////////////////////////////////////////////////////////
                // 将音频数据回调到大应用中
                if(s_aiFrameDataCallback != NULL)
                {
                    s_aiFrameDataCallback(audioAnalysis.audio_data, audioAnalysis.audio_data_length, audioAnalysis.frame_num, audioAnalysis.audio_type);
                }
            }
            else if ((audioAnalysis.audio_type == 2) && (audioAnalysis.frame_num < AI_COUNT)) // 骨导原始数据
            {
                // printf("num %d,len %d,type=%d\n", audioAnalysis.frame_num, audioAnalysis.audio_data_length, audioAnalysis.audio_type);
                appendToPcmFile(audioAnalysis.bone_filename, audioAnalysis.audio_data, audioAnalysis.audio_data_length);

                if (audioAnalysis.frame_num == 1)
                {
                    memset(soc_buffer_mic_bone, 0, SOC_MIC_LENGTH);
                    soc_buffer_mic_bone[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
                    soc_buffer_mic_bone[1] = 6;
                    soc_buffer_mic_bone[3] = dataType_bone; // 00 04表示骨导数据
                }
                intToUint8Array(audioAnalysis.frame_num, &soc_buffer_mic_bone[4]);

                intToUint8Array(audioAnalysis.audio_data_length, &soc_buffer_mic_bone[8]);
                memcpy(&soc_buffer_mic_bone[SEND_FRAME_HEAD_LEN], audioAnalysis.audio_data, audioAnalysis.audio_data_length * sizeof(uint8_t));

                if (version != 0)
                {
                    mtx_soc_sendData.lock();
                    serverSocket.sendData(soc_buffer_mic_bone, SOC_MIC_LENGTH);
                    mtx_soc_sendData.unlock();
                }
                // 将音频数据回调到大应用中
                if (s_aiFrameDataCallback != NULL)
                {
                    s_aiFrameDataCallback(audioAnalysis.audio_data, audioAnalysis.audio_data_length, audioAnalysis.frame_num, audioAnalysis.audio_type);
                }
            }
            else if ((audioAnalysis.audio_type == 3) && (audioAnalysis.frame_num < AI_COUNT)) // 气导+骨导数据
            {
                // printf("num %d,len %d,type=%d\n", audioAnalysis.frame_num, audioAnalysis.audio_data_length, audioAnalysis.audio_type);

                for (int i = 0; i < audioAnalysis.audio_data_length / 4; i++)
                {
                    audioAnalysis.air_audio_data[i * 2] = audioAnalysis.audio_data[4 * i];
                    audioAnalysis.air_audio_data[i * 2 + 1] = audioAnalysis.audio_data[4 * i + 1];
                    audioAnalysis.bone_audio_data[i * 2] = audioAnalysis.audio_data[4 * i + 2];
                    audioAnalysis.bone_audio_data[i * 2 + 1] = audioAnalysis.audio_data[4 * i + 3];
                }
                appendToPcmFile(audioAnalysis.air_filename, audioAnalysis.air_audio_data, audioAnalysis.audio_data_length / 2);
                appendToPcmFile(audioAnalysis.bone_filename, audioAnalysis.bone_audio_data, audioAnalysis.audio_data_length / 2);

                // air +bone model send data
                if (audioAnalysis.frame_num == 1)
                {
                    memset(soc_buffer_mic_air_bone, 0, SOC_MIC_LENGTH + PER_AUDIO_FRAME_LEN);

                    soc_buffer_mic_air_bone[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
                    soc_buffer_mic_air_bone[1] = 6;
                    soc_buffer_mic_air_bone[3] = dataType_air_bone; // 00 06表示air+bone
                }

                intToUint8Array(audioAnalysis.frame_num, &soc_buffer_mic_air_bone[4]);
                intToUint8Array(audioAnalysis.audio_data_length, &soc_buffer_mic_air_bone[8]);
                memcpy(&soc_buffer_mic_air_bone[SEND_FRAME_HEAD_LEN], audioAnalysis.audio_data, audioAnalysis.audio_data_length * sizeof(uint8_t));

                if (version != 0)
                {
                    mtx_soc_sendData.lock();
                    serverSocket.sendData(soc_buffer_mic_air_bone, SOC_MIC_LENGTH + PER_AUDIO_FRAME_LEN);
                    mtx_soc_sendData.unlock();
                }

                // 将音频数据回调到大应用中
                if (s_aiFrameDataCallback != NULL)
                {
                    s_aiFrameDataCallback(audioAnalysis.audio_data, audioAnalysis.audio_data_length, audioAnalysis.frame_num, audioAnalysis.audio_type);
                }
            }
            else // 帧类型错误，返回
            {
                ret = -1;
            }
        }
    }
    return ret;
}

int frame_analysis_function(uint8_t *data, unsigned int length)
{
    int ret;
    uint8_t frame_flag = 0;
    uint8_t from = 0;
    uint8_t to = 0;
    uint8_t command_id = 0;
    unsigned short data_length = 0;
    unsigned short check_sum_cal = 0;
    unsigned short check_sum_read = 0;
    uint8_t temp_buffer[FRAME_BUFFER_LENGTH_MAX] = {0};
    unsigned short temp_data_length = 0;

    if ((data == NULL) || (length > FRAME_BUFFER_LENGTH_MAX))
    {
        return -1;
    }
    else
    {
        memcpy(temp_buffer, save_buffer, save_data_length);   // 拷贝上一次未解析完数据
        temp_data_length = save_data_length + length;         // 计算要解析的数据总长度
        memcpy(&temp_buffer[save_data_length], data, length); // 拷贝这一次读取到的所有数据
    }

    for (int i = 0; i < temp_data_length; i++)
    {
        if (temp_buffer[i] == FRAME_FLAG) // 查找帧头标志位0xFE
        {
            if ((temp_data_length - i) >= FRAME_HEADER_LENGTH) // 判断剩余长度是否够解析帧头内容
            {
                from = temp_buffer[i + FRAME_FROM_INDEX];
                to = temp_buffer[i + FRAME_TO_INDEX];
                command_id = temp_buffer[i + FRAME_COMMAND_ID_INDEX];

                memcpy(&data_length, &temp_buffer[i + FRAME_DATA_LENGTH_INDEX], 2);
                data_length = big_to_little_u16(&data_length);

                // 副板->主板
                if ((data_length >= 2) && (data_length < FRAME_BUFFER_LENGTH_MAX) && (from == 0x02) && (to == 0x04)) // 判断读取到的数据长度是否有效，以及来源与目的是否是副板到主板
                {
                    frame_total_length = FRAME_TOTAL_LENGTH(data_length);
                    if ((i + frame_total_length) <= temp_data_length) // 判断读取数据是否够一整帧
                    {
                        memcpy(data_buffer, &temp_buffer[i], frame_total_length);                    // 保存一整帧数据
                        save_data_length = temp_data_length - frame_total_length;                    // 剩余数据下回解析
                        memcpy(save_buffer, &temp_buffer[i + frame_total_length], save_data_length); // 剩余数据下回解析

                        // 计算校验值
                        check_sum_cal = calc_crc16(data_buffer, FRAME_CHECK_DATA_LENGTH(data_length), CHECKSUM_INIT_VALUE);
                        check_sum_read = big_to_little_u16(&data_buffer[FRAME_CHECKSUM_INDEX(data_length)]);
                        if (check_sum_cal == check_sum_read) // 判断校验结果与校验位数据是否一致
                        {
                            // printf("data: from %02x to %02x command_id %02x length %d checksum %04x !\n", from, to, command_id, data_length, check_sum_read);

                            if (command_id == 0x21)
                            {
                                audio_frame_analysis_function(&data_buffer[FRAME_HEADER_LENGTH], data_length);
                            }
                            // 查询副板固件版本号回码
                            if (command_id == 0x01)
                            {
                                // printf("firmware_version response: %02x %02x %02x %02x %02x %02x\n", temp_buffer[i], from, to, command_id, data_buffer[FRAME_HEADER_LENGTH],data_length);
                                subplate_firmware_version_response_func(&data_buffer[FRAME_HEADER_LENGTH], data_length);
                            }
                        }
                        else
                        {
                            // 校验失败
                            if (real_time_recv_serial_data_flag)
                            {
                                printf("校验失败：%04x , %04x\n", check_sum_cal, check_sum_read);
                            }
                        }
                    }
                    else
                    {
                        // 数据不完整，继续等待
                        save_data_length = temp_data_length;
                        memcpy(save_buffer, temp_buffer, temp_data_length);
                        if (real_time_recv_serial_data_flag)
                        {
                            printf("不够解析整帧,数据不完整,继续等待,i = %d, length = %d\n", i, temp_data_length);
                        }
                        break;
                    }
                }
                // 上位机->主板
                else if ((from == 0x08) && (to == 0x04)) // 上位机到副板，副板转发到主板
                {
                    frame_total_length = FRAME_TOTAL_LENGTH(data_length);
                    // printf("host->main:%d\n",frame_total_length);

                    if ((i + frame_total_length) <= temp_data_length) // 判断读取数据是否够一整帧
                    {
                        memcpy(data_buffer, &temp_buffer[i], frame_total_length);                    // 保存一整帧数据
                        save_data_length = temp_data_length - frame_total_length;                    // 剩余数据下回解析
                        memcpy(save_buffer, &temp_buffer[i + frame_total_length], save_data_length); // 剩余数据下回解析

                        // 计算校验值
                        check_sum_cal = calc_crc16(data_buffer, FRAME_CHECK_DATA_LENGTH(data_length), CHECKSUM_INIT_VALUE);
                        check_sum_read = big_to_little_u16(&data_buffer[FRAME_CHECKSUM_INDEX(data_length)]);
                        if (check_sum_cal == check_sum_read) // 判断校验结果与校验位数据是否一致
                        {
                            if (((data_length == 1)) && (command_id == 0x27)) // 上位机->主板
                            {
                                // printf("recv_data: %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", temp_buffer[i], from, to, command_id, data_buffer[FRAME_HEADER_LENGTH - 2], data_buffer[FRAME_HEADER_LENGTH - 1], data_buffer[FRAME_HEADER_LENGTH], data_buffer[FRAME_HEADER_LENGTH + 1], data_buffer[FRAME_HEADER_LENGTH + 2]);
                                if (s_sppFrameDataCallback != NULL) // 将接收到的键值回调出去
                                {
                                    s_sppFrameDataCallback(data_buffer[FRAME_HEADER_LENGTH]);
                                }
                            }
                            else if (command_id == 0xFF)
                            {
                                if (s_testFrameDataCallback != NULL)
                                {
                                    s_testFrameDataCallback(data_buffer, frame_total_length);
                                }
                            }
                        }
                    }
                }

                // 副板->主板:响应数据
                else if (((data_length == 1)) && (data_length < FRAME_BUFFER_LENGTH_MAX) && (from == 0x02) && (to == 0x04)) // 判断读取到的数据长度是否有效，以及来源与目的是否是副板到主板
                {
                    frame_total_length = FRAME_TOTAL_LENGTH(data_length);
                    if ((i + frame_total_length) <= temp_data_length) // 判断读取数据是否够一整帧
                    {
                        memcpy(data_buffer, &temp_buffer[i], frame_total_length);                    // 保存一整帧数据
                        save_data_length = temp_data_length - frame_total_length;                    // 剩余数据下回解析
                        memcpy(save_buffer, &temp_buffer[i + frame_total_length], save_data_length); // 剩余数据下回解析

                        // 计算校验值
                        check_sum_cal = calc_crc16(data_buffer, FRAME_CHECK_DATA_LENGTH(data_length), CHECKSUM_INIT_VALUE);
                        check_sum_read = big_to_little_u16(&data_buffer[FRAME_CHECKSUM_INDEX(data_length)]);

                        if (check_sum_cal == check_sum_read) // 判断校验结果与校验位数据是否一致
                        {
                            // 音频数据回码
                            if (command_id == 0x20)
                            {
                                audio_response_func(&data_buffer[FRAME_HEADER_LENGTH], data_length);
                            }
                        }
                        else
                        {
                            // 校验失败
                            if (real_time_recv_serial_data_flag)
                            {
                                printf("校验失败：%04x , %04x\n", check_sum_cal, check_sum_read);
                            }
                        }
                    }
                    else
                    {
                        // 数据不完整，继续等待
                        save_data_length = temp_data_length;
                        memcpy(save_buffer, temp_buffer, temp_data_length);
                        if (real_time_recv_serial_data_flag)
                        {
                            printf("不够解析整帧,数据不完整,继续等待,i = %d, length = %d\n", i, temp_data_length);
                        }
                        break;
                    }
                }
                else
                {
                    // 数据错误
                    if (real_time_recv_serial_data_flag)
                    {
                        printf("数据长度：%d，from：%02x，to：%02x\n", data_length);
                    }
                }
            }
            else
            {
                // 数据不完整，继续等待
                save_data_length = temp_data_length;
                memcpy(save_buffer, temp_buffer, temp_data_length);
                if (real_time_recv_serial_data_flag)
                {
                    printf("不够解析帧头，数据不完整，继续等待\n");
                }
                break;
            }
        }
        break; // 退出for循环
    }
    return ret;
}

// 数据帧解析线程函数
void *frame_analysis_pthread_function(void *arg)
{
    uint8_t read_buffer[FRAME_BUFFER_LENGTH_MAX]; // 65536
    while (true)
    {
        mtx_ringbuffer.lock();
        validLen = serialData.getRingbufferValidLen();
        if (validLen > 0)
        {
            readLen = serialData.readRingbuffer(read_buffer, validLen);
            frame_analysis_function(read_buffer, readLen);
        }
        mtx_ringbuffer.unlock();
    }
}

// 串口初始化
int serial_init(void)
{
    int ret;
    int arg = 100;
    //
    ret = open_serial_port();
    if (ret == -1)
    {
        return ret;
    }
    //
    ret = set_serial_attribs();
    if (ret == -1)
    {
        return ret;
    }

    // 循环缓冲区初始化
    serialData.bufferSize = RB_MAX_SIZE;
    serialData.initRingbuffer();
    // 创建串口线程
    ret = pthread_create(&serial_read_pthread, NULL, serial_recv_pthread_function, (void *)&arg);
    if (ret == -1)
    {
        printf("创建串口接收线程失败！\n");
        return ret;
    }
    sleep(1);
    // 创建数据帧解析线程
    ret = pthread_create(&frame_analysis_pthread, NULL, frame_analysis_pthread_function, (void *)&arg);
    if (ret == -1)
    {
        printf("创建数据分析线程失败！\n");
        return ret;
    }

    return ret;
}
// 主板-->副板/上位机
int frame_package_function(protocal_list_t instruct, void *data, unsigned short length)
{
    int ret;
    uint8_t send_buffer[FRAME_BUFFER_LENGTH_MAX] = {0};
    unsigned short data_length = 0;
    unsigned short check_sum = 0;

    // 判断传入参数
    if ((data == NULL) && (length != 0))
    {
        return -1;
    }
    // 填充帧内容
    send_buffer[FRAME_FLAG_INDEX] = 0xFE; // 帧头标准
    send_buffer[FRAME_FROM_INDEX] = 0x04; // 从主板

    if (sub_flg) // true
    {
        send_buffer[FRAME_TO_INDEX] = 0x08; // 发往上位机
    }
    else
    {
        send_buffer[FRAME_TO_INDEX] = 0x02; // 发往副板(slave)
    }

    send_buffer[FRAME_COMMAND_ID_INDEX] = (uint8_t)instruct; // 指令
    data_length = big_to_little_u16(&length);
    memcpy(&send_buffer[FRAME_DATA_LENGTH_INDEX], &data_length, sizeof(data_length)); // 有效数据长度
    memcpy(&send_buffer[FRAME_DATA_START_ADDR_INDEX], data, length);                  // 有效数据
    // 计算校验值
    check_sum = calc_crc16(send_buffer, FRAME_CHECK_DATA_LENGTH(length), CHECKSUM_INIT_VALUE);
    // printf("check_sum = %x\n", check_sum);
    check_sum = big_to_little_u16(&check_sum);
    // printf("check_sum = %x\n", check_sum);
    memcpy(&send_buffer[FRAME_CHECKSUM_INDEX(length)], &check_sum, sizeof(check_sum)); // 校验值

    ret = serial_send_function(send_buffer, FRAME_TOTAL_LENGTH(length));

    return ret;
}

void query_firmware_info_cmd(int flg)
{
    frame_package_function(inquire_firmware_info_cmd, NULL, flg);
}

int ptt_up_data_switch_cmd(int flg)
{
    int ret = 0;
    uint8_t send_data = flg;

    sub_flg = true;
    ret = frame_package_function(up_data_switch_cmd, &send_data, sizeof(send_data));
    sub_flg = false;

    return ret;
}

int lip_label_data_send_cmd(int flg)
{
    int ret = 0;
    uint8_t send_data[2] = {0};

    send_data[1] = static_cast<uint8_t>(flg); // 唇图识别标签,转化为unsigned char

    sub_flg = true;
    ret = frame_package_function(label_data_send_cmd, &send_data, sizeof(send_data));
    sub_flg = false;

    return ret;
}

int display_mode_switch_cmd(int flg)
{
    int ret = 0;
    uint8_t send_data = 0;

    switch (flg)
    {
    case 0:
        send_data = 0; // 切换到待机模式，停止上下行播放
        ret = frame_package_function(mode_switch_cmd, &send_data, sizeof(send_data));
        break;
    case 1:
        send_data = 1; // 切换到有线通信，启动有线下行播放
        ret = frame_package_function(mode_switch_cmd, &send_data, sizeof(send_data));
        break;
    case 2:
        send_data = 2; // 切换到蓝牙通信，启动蓝牙
        ret = frame_package_function(mode_switch_cmd, &send_data, sizeof(send_data));
        break;

    default:
        printf("display_mode_switch_cmd:default:%d\n", flg);
        ret = -1;
        break;
    }

    return ret;
}

int uart_tip_data(int read_data)
{
    int ret = 0;
    uint8_t send_data = 0;

    switch (read_data)
    {
    case 1:
        send_data = 1;
        break;
    case 2:
        send_data = 2;
        break;
    case 3:
        send_data = 3;
        break;
    case 4:
        send_data = 4;
        break;
    case 5:
        send_data = 5;
        break;
    case 6:
        send_data = 6;
        break;
    case 7:
        send_data = 7;
        break;
    case 8:
        send_data = 8;
        break;
    case 9:
        send_data = 9;
        break;
    case 10:
        send_data = 10;
        break;
    case 11:
        send_data = 11;
        break;
    case 0:
        /* code */
        return ret;

    default:
        printf("uart_tip_data:default:%d\n", read_data);
        return -1;
    }
    ret = frame_package_function(prompt_tone_play_cmd, &send_data, sizeof(send_data));

    return ret;
}

int battery_status_notify_cmd_function(int flag, int vol, int cap)
{
    int ret = 0;
    uint8_t send_data[4] = {0};

    send_data[0] = flag;
    int_to_hex_array(vol, &send_data[1]);
    send_data[3] = cap;

    ret = frame_package_function(battery_status_notify_cmd, &send_data, sizeof(send_data));

    return ret;
}

int display_inquire_firmware_info_cmd_function(void)
{
    int ret = 0;

    ret = frame_package_function(inquire_firmware_info_cmd, NULL, 0);

    return ret;
}

int mic_data_request_cmd_function(int flg)
{
    int ret = 0;
    unsigned int time = 1;
    uint8_t send_data[2] = {0};

    switch (flg)
    {
    case 1:
        send_data[1] = 1; // 气导 原始信号
        break;
    case 2:
        send_data[1] = 2; // 骨导 原始信号
        break;
    case 3:
        send_data[1] = 3; // 气导+骨导 原始信号
        break;
        // default:
        //     printf("audio:mic_data_request_cmd_function:%d!\n", flg);
        //     break;
    }

    // 开始传输音频数据
    send_data[0] = 1;
    ret = frame_package_function(mic_adta_request_cmd, &send_data, sizeof(send_data));

    this_thread::sleep_for(std::chrono::seconds(time) + std::chrono::milliseconds(800)); // 延时1s+800ms=1.8s
    // 停止传输音频数据
    send_data[0] = 0;
    ret = frame_package_function(mic_adta_request_cmd, &send_data, sizeof(send_data));

    return ret;
}

int command_uart_transform(int id, int flg)
{
    int ret = 0;
    switch (id)
    {
    case 0:
        query_firmware_info_cmd(flg); // 固件版本信息查询指令
        break;
    case 1:
        ret = uart_tip_data(flg); // 提示音播放
        break;
    case 2:
        ret = display_mode_switch_cmd(flg); // 通信模式切换指令:有线/蓝牙
        break;
    case 3:
        ret = ptt_up_data_switch_cmd(flg); // PTT按下与抬起
        break;
    case 4:
        ret = lip_label_data_send_cmd(flg); // 唇图识别标签
    case 5:
        ret = mic_data_request_cmd_function(flg); // 副板到主板传输音频:1-气导;2-骨导;3-骨+气
        break;
    case 7:
        image_info_uart_upload_cmd(flg); // 传图像信息功能:有线485/蓝牙SPP
        break;
    case 8:
        mode_state_uart_upload_cmd(flg); // 模式状态的UART上传功能->上位机
        break;
    case 9:
        lip_label_uart_upload_cmd(flg); // 单纯唇图标签上传
        break;
    case 10:
        host_main_data_trans(); // 上位机_>主板的数据接收
        break;
    case 11:
        audio_pcm_uart_upload_func(flg); // lip label->pcm 发送到副板
        break;
    case 12:
        mode_state_to_subplate(flg);
        break;
    case 13:
        poweroff_cmd_send_func(flg);
        break;
    case 14:
        firmware_version_to_host_send_func(flg);
        break;

    default:
        printf("command_uart_transform:%d,%d\n", id, flg);
        break;
    }
    return ret;
}

// 图像信息上传函数
void image_info_uart_upload_cmd(int flg)
{
    int ret = 0;
    uint8_t send_data[11] = {0};

    send_data[1] = SEND_IMG_WIDTH;                    // 112
    send_data[3] = SEND_IMG_HEIGHT;                   // 112
    int_to_hex_array(SEND_IMG_Y_SIZE, &send_data[6]); // 12544
    send_data[8] = 1;                                 // 0：YUV-NV12; 1：Y                             // 00：图像格式YUV-NV12
    send_data[10] = SEND_PKG_CNT_Y;                   // 13 pkgs
    if (flg == 0)                                     // 表示蓝牙通信
    {
        sub_flg = true;
        ret = frame_package_function(img_info_send_cmd, &send_data, sizeof(send_data));
        sub_flg = false;
    }
    else if (flg == 1) // 表示有线485通信
    {
        youxian_485_upload(img_info_send_cmd, &send_data, sizeof(send_data));
    }
}

// 图像数据上传函数,数据包长度1028/516,其中1024/512表示图像数据长度
void image_data_uart_upload_cmd(int pkg_num, int pkg_size, uint8_t *data)
{
    int ret = 0;
    if (pkg_size == PER_PKG_IMG_SIZE) // 1024
    {
        uint8_t send_data[SEND_PKG_SIZE] = {0}; // 1028
        send_data[1] = pkg_num;
        int_to_hex_array(pkg_size, &send_data[2]);
        memcpy(&send_data[4], data, pkg_size);

        sub_flg = true;
        ret = frame_package_function(img_data_send_cmd, &send_data, sizeof(send_data));
        sub_flg = false;
    }
    else if (pkg_size == PER_PKG_IMG_SIZE / 2) // 512
    {
        uint8_t send_data[SEND_PKG_SIZE_516] = {0}; // 516
        send_data[1] = pkg_num;
        int_to_hex_array(pkg_size, &send_data[2]);
        memcpy(&send_data[4], data, pkg_size);

        sub_flg = true;
        ret = frame_package_function(img_data_send_cmd, &send_data, sizeof(send_data));
        sub_flg = false;
    }
}

// 模式状态上传
void mode_state_uart_upload_cmd(int stateValue)
{
    int ret = 0;
    uint8_t send_data[2] = {0};

    send_data[1] = stateValue; // 模式状态值

    sub_flg = true;
    ret = frame_package_function(mode_state_send_cmd, &send_data, sizeof(send_data));
    sub_flg = false;
}

void intToUint8Array(int number, uint8_t uint8Array[4])
{
    uint8Array[0] = (number >> 24) & 0xFF; // 提取最高字节
    uint8Array[1] = (number >> 16) & 0xFF; // 提取次高字节
    uint8Array[2] = (number >> 8) & 0xFF;  // 提取次低字节
    uint8Array[3] = number & 0xFF;         // 提取最低字节
}

// 主板->上位机：单独唇图标签上传函数
void lip_label_uart_upload_cmd(int labelValue)
{
    uint8_t send_data[4] = {0};

    intToUint8Array(labelValue, send_data);

    sub_flg = true;
    int ret = frame_package_function(lip_label_send_cmd, &send_data, sizeof(send_data));
    sub_flg = false;
}
// 上位机到主板的数据接收模块
void host_main_data_trans(void)
{
    // 串口接收与解析线程等待
    pthread_join(frame_analysis_pthread, NULL);
    pthread_join(serial_read_pthread, NULL);
}

// uint16数组转换为uint8_t数组
vector<uint8_t> convertUint16ToUint8Array(const std::vector<uint16_t> &uint16Data)
{
    // 创建一个足够大的vector来存储转换后的数据 ,每个uint16_t转换为两个uint8_t，所以总大小是uint16Data的两倍
    std::vector<uint8_t> uint8Data(uint16Data.size() * 2);

    // 遍历uint16_t数组，将每个元素拆分为两个uint8_t
    for (size_t i = 0; i < uint16Data.size(); ++i)
    {
        // 小端字节序（LE）
        uint8Data[i * 2] = static_cast<uint8_t>(uint16Data[i] & 0xFF);            // 低字节
        uint8Data[i * 2 + 1] = static_cast<uint8_t>((uint16Data[i] >> 8) & 0xFF); // 高字节
    }
    return uint8Data;
}

// 将PCM（16K/16bit/1channel）数据读取到uint16的数组,再转换为uint8数组
vector<uint8_t> readPCMFileToInt8Array(const std::string &filename)
{
    std::ifstream file(filename, std::ios::binary | std::ios::ate); // 二进制形式打开，并且打开时文件指针立即置于文件末尾
    if (!file.is_open())
    {
        std::cerr << "无法打开文件 " << filename << std::endl;
        throw std::runtime_error("文件打开失败");
    }

    // 获取文件大小(单位:字节)，并转换为16位样本的数量
    std::streamsize size = file.tellg();
    if (size % 2 != 0)
    {
        throw std::runtime_error("文件大小不是16位样本的整数倍");
    }
    size_t numSamples = size / 2;

    file.seekg(0, std::ios::beg); // 重置到文件开头

    // 创建一个足够大的vector来存储数据
    std::vector<uint16_t> pcmData(numSamples);

    // 读取数据到vector
    file.read(reinterpret_cast<char *>(pcmData.data()), size);
    if (!file)
    {
        std::cerr << "读取文件时发生错误" << std::endl;
        throw std::runtime_error("文件读取错误");
    }
    // 关闭文件
    file.close();

    // uint16->uint8 array
    vector<uint8_t> u8Data = convertUint16ToUint8Array(pcmData); // u8Data.size()=numSamples*2=size
    return u8Data;
}

// 电台模块:音频PCM通过UART口传输副板，副板收到0x23指令后通过音频线出去
void audio_pcm_uart_upload_func(int label)
{
    int ret = 0;
    snprintf(viDianTaiCmdFinal, sizeof(viDianTaiCmdFinal), "%s/sessionAir0_%d.pcm", PCM_PATH, label);
    uint8_t send_data[PER_AUDIO_FRAME_LEN] = {0}; // 480

    std::vector<uint8_t> pcmData8Bit = readPCMFileToInt8Array(viDianTaiCmdFinal);

    int num = pcmData8Bit.size() / PER_AUDIO_FRAME_LEN;
    printf("%s,%d,%d\n", viDianTaiCmdFinal, pcmData8Bit.size(), num);

    for (int i = 0; i < num; i++)
    {
        for (int j = 0; j < PER_AUDIO_FRAME_LEN; j++)
        {
            send_data[j] = pcmData8Bit[i * PER_AUDIO_FRAME_LEN + j];
        }
        // appendToPcmFile("/data/send.pcm", send_data, PER_AUDIO_FRAME_LEN); // test send.pcm
        ret = frame_package_function(auido_presentations_cmd, &send_data, sizeof(send_data));
        std::this_thread::sleep_for(std::chrono::milliseconds(15)); // 15ms
    }
}

void mode_state_to_subplate(int flg) // 主板发送模式状态到副板，决定上行声音是否开启(0x32)
{
    int ret = 0;
    uint8_t send_data = 0;

    send_data = flg; // 模式状态值

    ret = frame_package_function(mode_state_send_cmd_to_subplate, &send_data, sizeof(send_data));
}
// 向副板发送关机指令
void poweroff_cmd_send_func(int flg)
{
    frame_package_function(poweroff_notify_cmd, NULL, flg);
}

void firmware_version_to_host_send_func(int flg)
{
    int ret = 0;
    uint8_t send_data[4] = {0};

    int year = 2025;
    int month = 7;
    int day = 29;
    printf("current mainboard firmware version:%d.%d.%d\n", year, month, day);
    // firmware version num
    send_data[0] = (year / 256) % 256; // 高位
    send_data[1] = year % 256;         // 低位
    send_data[2] = month;
    send_data[3] = day;

    if (flg == 0) // bluetooth spp send
    {
        sub_flg = true;
        ret = frame_package_function(firmware_version_info_host_cmd, &send_data, sizeof(send_data));
        sub_flg = false;
    }
    else if (flg == 1) // youxian 485 send
    {
        youxian_485_upload(firmware_version_info_host_cmd, &send_data, sizeof(send_data));
    }
}

void dataset_num_send_func(int flg, int comm)
{
    int ret = 0;
    uint8_t send_data[4] = {0};
    intToUint8Array(flg, send_data);

    if (comm == 0) // bluetooth spp send
    {
        sub_flg = true;
        ret = frame_package_function(dataset_num_info_send_cmd, &send_data, sizeof(send_data));
        sub_flg = false;
    }
    else if (comm == 1) // youxian 485 send
    {
        youxian_485_upload(dataset_num_info_send_cmd, &send_data, sizeof(send_data));
    }
}
/*-------------------------------------------------------------------
(1)UART传输指令函数,只有pam1==6时，pam2:充电状态，pam3:电池电量，pam4: 电池电压;
(2)pam1==7:表示上传图像信息,pam2=0:通过蓝牙SPP上传;pam2=1:通过有线485上传;
(3)其余pam3,pam4==0;
(4)pam1=8,pam2=96/97:表示模式状态值
(5)pam1=9,pam2=标签值
(6)pam1=10:表示上位机->主板的数据接收
(7)pam1=11: uart_commid 11 标签值(电台发送)
(8)pam1=12: uart_commid 12 0/1:对应模式状态的发送
(9)pam1=13: uart_commid 13 0: 向副板发送关机指令
(10)pam1=0: uart_commid 0 0: 查询副板固件版本号
---------------------------------------------------------------------*/
void uart_main_func(int pam1, int pam2, int pam3, int pam4)
{
    int rst = 0;
    printf("param:%d,%d,%d,%d\n", pam1, pam2, pam3, pam4);

    // uart transformer commid
    if (pam1 == 6)
    {
        rst = battery_status_notify_cmd_function(pam2, pam3, pam4); // 电池电量的UART传输
    }
    else
    {
        rst = command_uart_transform(pam1, pam2);
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 每个指令间隔100ms
}

// 查询文件夹中文件的数量
int InFolder_File_Num(const char *folder_path)
{
    struct dirent *entry;
    int file_count = 0;

    DIR *dir = opendir(folder_path);
    if (dir == nullptr)
    {
        std::cerr << "Error opening directory: " << folder_path << std::endl;
        return -1;
    }

    while ((entry = readdir(dir)) != nullptr)
    {
        if (entry->d_type == DT_REG)
        {
            file_count++;
        }
    }
    closedir(dir);
    return file_count;
}

/*-----------------------演示系统v2.0迭代-----------------------*/
void server_client_frame_package_function(server_client_protocal_list instruct, void *data, unsigned short length)
{
    uint8_t soc_buffer[SEND_BUF_SIZE] = {0};                     // 初始化buffer为0
    uint8_t pkg_num = 0;                                         // 包号
    uint8_t pkg_data[SEND_BUF_SIZE - SEND_FRAME_HEAD_LEN] = {0}; // 去掉帧头的有效数据

    soc_buffer[0] = static_cast<uint8_t>(instruct);
    soc_buffer[1] = length;
    memcpy(&soc_buffer[2], data, length);

    // send data
    mtx_soc_sendData.lock();
    serverSocket.sendData(soc_buffer, length + 2);
    mtx_soc_sendData.unlock();

    // printf("send soc_buffer data:\n");
    for (int i = 0; i < length + 2; i++)
    {
        printf("0x%02x ", soc_buffer[i]);
    }
    printf("\n");
    this_thread::sleep_for(std::chrono::milliseconds(100));
}

// 预发送 air:0x31 0x06 0x00 0x02 + data_length
void custom_audio_presend_func(server_client_protocal_list instruct, int send_data_len)
{
    uint8_t send_data[6] = {0};
    send_data[1] = static_cast<uint8_t>(instruct); // 表示预发送的数据类型
    intToUint8Array(send_data_len, &send_data[2]);

    server_client_frame_package_function(msg_presend_instruct, &send_data, sizeof(send_data));
}

// 耳机数据（视频格式预备）
void custom_video_presend_func(int width, int height,int data_len)
{
    uint8_t send_data[16] = {0};   // 0x10
    send_data[1] = dataType_video; // video

    intToUint8Array(data_len, &send_data[2]);

    intToUint8Array(width, &send_data[6]);
    intToUint8Array(height, &send_data[10]);

    send_data[15] = dataType_video; // 0x00 0x01:视频帧格式nv12

    server_client_frame_package_function(msg_presend_instruct, &send_data, sizeof(send_data));
}

// 耳机数据（结果格式预备）
void results_presend_func(void)
{
    uint8_t send_data[6] = {0};
    send_data[1] = dataType_result;
    send_data[5] = 0x04; // 结果数据长度

    server_client_frame_package_function(msg_presend_instruct, &send_data, sizeof(send_data));
}

// 耳机传感器数据（result）
void results_send_func(int results)
{
    memset(public_soc_buffer, 0, SEND_BUF_SIZE);
    public_soc_buffer[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
    public_soc_buffer[1] = 0x06;
    public_soc_buffer[3] = dataType_result;
    public_soc_buffer[SEND_FRAME_HEAD_LEN - 1] = 0x04; // 标签识别结果发送的数据长度

    intToUint8Array(results, &public_soc_buffer[SEND_FRAME_HEAD_LEN]);

    printf("result soc send\n");
    for (int i = 0; i < SEND_FRAME_HEAD_LEN + 4; i++)
    {
        printf("%02x ", public_soc_buffer[i]);
    }
    printf("\n");

    serverSocket.sendData(public_soc_buffer, SEND_FRAME_HEAD_LEN + 4);
}

// 耳机传感器数据（result+scores）
void results_scores_send_func(int results, int scores)
{
    memset(public_soc_buffer, 0, SEND_BUF_SIZE);
    public_soc_buffer[0] = static_cast<uint8_t>(msg_sensor_data_instruct);
    public_soc_buffer[1] = 0x06;
    public_soc_buffer[3] = dataType_result;
    public_soc_buffer[SEND_FRAME_HEAD_LEN - 1] = 0x04; // 标签识别结果发送的数据长度

    intToUint8Array(results, &public_soc_buffer[SEND_FRAME_HEAD_LEN]);
    intToUint8Array(scores, scores_buffer);

    public_soc_buffer[SEND_FRAME_HEAD_LEN] = scores_buffer[2];
    public_soc_buffer[SEND_FRAME_HEAD_LEN + 1] = scores_buffer[3];

    printf("result soc send\n");
    for (int i = 0; i < SEND_FRAME_HEAD_LEN + 4; i++)
    {
        printf("%02x ", public_soc_buffer[i]);
    }
    printf("\n");

    serverSocket.sendData(public_soc_buffer, SEND_FRAME_HEAD_LEN + 4);
}

// 结束发送:0x32 0x02 0x00 data_type
void data_type_finish_send_func(server_client_protocal_list instruct)
{
    uint8_t send_data[2] = {0};
    send_data[1] = static_cast<uint8_t>(instruct);

    server_client_frame_package_function(msg_finish_send_instruct, &send_data, sizeof(send_data));
}

// power info send func
void power_info_send_func(int powerValue)
{
    uint8_t send_data[6] = {0};
    send_data[1] = 0x01;
    intToUint8Array(powerValue, &send_data[2]);
    server_client_frame_package_function(msg_power_info_instruct, &send_data, sizeof(send_data));
}

// 正式发送气导数据:custom_air_audio_send_data
void custom_air_audio_send_func()
{
    uint8_t send_data[2] = {0};
    send_data[1] = 2;

    server_client_frame_package_function(msg_sensor_data_instruct, &send_data, sizeof(send_data));
}

double getTimeInMilliseconds()
{
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000.0 + ts.tv_nsec / 1e6;
}